package com.example.test.flow

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlin.system.measureTimeMillis


@ExperimentalCoroutinesApi
suspend fun main() = runBlocking {
    launch {
        for (j in 1..5) {
            delay(100)
            println("I'm not blocked $j")
        }
    }

    flow {
        for (i in 1..5) {
            delay(100)
            emit(i)
        }
    }.collect { println(it) }

    println("Done")
}

suspend fun test6() {
    withTimeoutOrNull(2500) {
        flow {
            for (i in 1..5) {
                delay(1000)
                emit(i)
            }
        }.collect {
            println(it)
        }
    }

    println("Done")
}

suspend fun test1() {
    flow {
        repeat(10, {
            delay(100)
            emit(10 + it)
        })
    }.collect {
        println(it)
    }
}

suspend fun test2() {
    listOf<Int>(1, 2, 3, 4, 5).asFlow().onEach {
        println("oneach $it")
        delay(100)
    }.collect {
        println("collect $it")
    }
}

suspend fun test3() {
    channelFlow<Int> {
        repeat(10) {
            delay(100)
            send(it)
        }
    }.collect {
        println(it)
    }
}

suspend fun test4() {
    val time = measureTimeMillis {
        flow {
            for (i in 1..5) {
                delay(100)
                emit(i)
            }
        }.collect {
            delay(100)
            println(it)
        }
    }

    println("cost sync $time ")

    val time1 = measureTimeMillis {
        channelFlow {
            for (i in 1..5) {
                delay(100)
                send(i)
            }
        }.collect {
            delay(100)
            println(it)
        }
    }

    println("cost async $time1 ")

    val time2 = measureTimeMillis {
        flow {
            for (i in 1..5) {
                delay(100)
                emit(i)
            }
        }.flowOn(Dispatchers.IO)
            .collect {
                delay(100)
                println(it)
            }
    }

    println("cost sync dispatcher $time2 ")
}

suspend fun test5() {

    println("${Thread.currentThread().name} ")
    flow {
        repeat(5) {
            println("emit    ${Thread.currentThread().name}: $it")
            delay(100)
            emit(it)
        }
    }.map {
        "map $it"
    }.flowOn(Dispatchers.Main)
        .collect {
            println("collect ${Thread.currentThread().name}: $it")
        }
}